#ifndef __CComponentServer_H__
#define __CComponentServer_H__

#include "compfwk/CComponentFactory.h"
#include "compfwk/IComponentServer.h"

namespace compfwk
{
    /**
     * \brief Singleton server that manages a type of components
     *
     * It has the following responsibilities:
     *   Create components using a component factory
     *   Retrieve the component of this type for an entity if 
     *   it has the component
     *   Update all the components of its type
     */
    template< TComponent >
    class CComponentServer : public IComponentServer
    {
    public:
        //Returns the unique instance of the Component Server
        static CComponentServer& Instance( void );

        //! Create an instance of the type TComponent
        //! Returns the new component created if it didn't exist.
        //! If it already existed a component of this type for the id
        //! passed as argument, the old one is returned
        bool New( int m_eid );

        //! Search for the component of the type TComponent corresponding
        //! to the entity with the id passed as argument
        //! Returns null( 0 ) if it didn't exist.
        TComponent* Search( int m_eid ) const;

        //! Update all the components
        void Update( void );

        //! Returns the type of the components this server manages
        //! as a string
        const CString& GetType( void ) const;

    private:
        //======================== DATA MEMBERS==============================//
        //! The factory that creates the component instances
        CComponentFactory< TComponent > m_factory;

        CHashMap< int, TComponent* > m_hm_comp;

        //! Default constructor
        CComponentServer( );

        //! Copy constructor
        CComponentServer( const CComponentServer& ar_comp_srv );

        //! Assignment operator
        CComponentServer& operator= ( const CComponentServer& ar_comp_srv );

        //! Destructor
        ~CComponentServer( );
    };

    template< typename TComponent >
    static CComponentServer& CComponentServer::Instance( void )
    {
        static CComponentServer< TComponent > instance;

        return instance;
    }

    template< typename TComponent >
    CComponentServer::CComponentServer( ) : m_factory( ), m_hm_comp( )
    {
    }

    template< typename TComponent >
    CComponentServer::~CComponentServer( )
    {
    }

    template< typename TComponent >
    bool CComponentServer::New( int a_eid )
    {
        TComponent* p_new = m_factory.Create( a_eid );

        bool result = m_hm_comp.insert( a_eid, p_new ).second;

        return result;
    }

    template< typename TComponent >
    TComponent* CComponentServer::Search( int a_eid ) const
    {
        CHashMap::iterator it( m_hm_comp.find( a_eid ) );
        if( it != m_hm_find.end( ) )
            return *it;
        else
            return (TComponent*)0;
    }

    template< typename TComponent >
    void CComponentServer::Update( void )
    {
        CHashMap::iterator it( m_hm_comp.begin( ) );
        CHashMap::iterator end( m_hm_comp.end( ) );
        for( ; it != end; ++it )
            (*it)->Update( );
    }

    template< typename TComponent >
    CString CComponentServer::GetType( void ) const
    {
        return m_factory.GetType( );
    }

}
#endif